package com.example.drools.spring.core.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import com.example.drools.spring.core.RuleEngine;
import com.example.drools.spring.core.helper.RuleTransformHelper;
import com.example.drools.spring.dao.RuleRepository;
import com.example.drools.spring.entity.DroolEntity;
import com.example.drools.spring.entity.DroolModel;
import com.example.drools.spring.entity.KieResoure;
import com.example.drools.spring.entity.db.Rule;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.drools.compiler.kie.builder.impl.InternalKieModule;
import org.drools.compiler.kie.builder.impl.KieContainerImpl;
import org.kie.api.KieServices;
import org.kie.api.builder.KieBuilder;
import org.kie.api.builder.KieFileSystem;
import org.kie.api.runtime.KieSession;
import org.kie.api.runtime.rule.FactHandle;
import org.springframework.stereotype.Service;

/**
 * @author ddsyw
 * @version 1.0
 * @date 2021/12/29 3:01 下午
 */
@Service
@Slf4j
public class ProductRuleEngineImpl implements RuleEngine {

    @Resource
    private KieFileSystem kieFileSystem;

    @Resource
    private KieSession kieSession;

    @Resource
    private RuleRepository ruleRepository;

    @Resource
    private KieContainerImpl kieContainer;

    @Override
    public <T extends DroolEntity> void executeRuleEngine(T drool) {
        kieSession.insert(drool);
        kieSession.fireAllRules();
    }

    @Override
    public void executeRuleEngine(Object... drools) {
        if (Objects.isNull(drools)) {
            return;
        }
        List<FactHandle> handleList = new ArrayList<>();
        try {
            for (Object t : drools) {
                if (Objects.nonNull(t)) {
                    FactHandle handle = kieSession.insert(t);
                    handleList.add(handle);
                }
            }
            //需要删除 执行handle 不然会有影响
            kieSession.fireAllRules();
            handleList.forEach(factHandle -> kieSession.delete(factHandle));
        } catch (Exception e) {
            log.error("execute rule error:{}", ExceptionUtil.getMessage(e));
        }
    }

    @Override
    public void initEngine() {
        //todi nothing
    }

    @Override
    public void refreshEnginRule() {
        Rule ruleDAO = ruleRepository.getOne(1L);
        if (Objects.isNull(ruleDAO) && StringUtils.isBlank(ruleDAO.getRule())) {
            return;
        }
        Optional<DroolModel> droolModelo = RuleTransformHelper.transform(ruleDAO.getRule());
        if (droolModelo.isPresent() && Objects.nonNull(droolModelo.get())) {
            Map<String, KieResoure> kieResoureMap = RuleTransformHelper.transFromDroolModel(
                Arrays.asList(droolModelo.get()));
            if (CollectionUtil.isNotEmpty(kieResoureMap)) {
                kieResoureMap.forEach((key, val) -> {
                    kieFileSystem.write(key, val.getResoure());
                });
                KieBuilder kieBuilder = KieServices.Factory.get().newKieBuilder(kieFileSystem);
                kieBuilder.buildAll();
                kieContainer.updateToKieModule((InternalKieModule) kieBuilder.getKieModule());
            }
        }
    }
}
